home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / audio / tablenet / tablenet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  14.1 KB  |  431 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*********************************************************************** 
  18.  * tableNet.c:  
  19.  *    Generates AIFF-C file containing eight single, cycle waveforms 
  20.  *        stored in the following order:
  21.  *
  22.  *    1   non-bandlimited sawtooth 
  23.  *    2   non-bandlimited triangle 
  24.  *    3   non-bandlimited pulse wave (25% duty cycle)
  25.  *    4   non-bandlimited square wave (50% duty cycle)
  26.  *    5   non-bandlimited pulse wave (75% duty cycle)
  27.  *    6   sine wave 
  28.  *    cosine wave 
  29.  *    3 harmonic wave (1st, 5th, 9th harmonics)
  30.  *    
  31.  *    To inspect file, use soundeditor, a graphical waveform editor.
  32.  *    A bug in released versions of soundeditor yields a waveform
  33.  *    displayed upside down (display only) and clips the waveform values
  34.  *    exceeding range [-32000 .. 32000] (display only).
  35.  *  
  36.  *                Written by Gints Klimanis 
  37.  *            Silicon Graphics Computer Systems
  38.  *                    1992
  39.  *********************************************************************** */
  40. #include <stdio.h>
  41. #include <audio.h>
  42. #include <math.h>
  43. #include <stdlib.h>
  44. #include "audiofile.h"
  45.  
  46. AFfilesetup    newSetUp;
  47. AFfilehandle    sourceFile;
  48.  
  49. double        *cycle;
  50. double        *sineTable;
  51. short        *output;
  52. int        numWaves;
  53. int        waveLength = 4096;
  54.  
  55. /* a single cycle of waveform can contain up to (length of cycle in samples)/2
  56. harmonics without aliasing.  However, when changing the playback rate of the 
  57. waveforms to output various pitches, the high frequencies cause noticable
  58. aliasing and jitter noise. 
  59. */
  60. #define        MAX_HARMONICS 200
  61. double        amplitudes[MAX_HARMONICS];
  62. double        phases[MAX_HARMONICS];
  63.  
  64. double        initialAmplitude = 32767.0;
  65. double        samplingRate = 44100.0;
  66. char        sourceFileName[1000];
  67.  
  68. double        pi, twoPi;
  69.  
  70. #define FALSE 0
  71. #define TRUE 1
  72.  
  73. /**************************************************************** 
  74.  * DoublesToShorts:    convert input buffer of DOUBLE to output buffer 
  75.  *            of SHORT.  Saturate option to 16-bits. 
  76.  *****************************************************************/
  77.     void 
  78. DoublesToShorts(double *in, short *out, long length, int saturate)
  79.     /* in:            base address of input data file
  80.        out:            base address of output data file
  81.        length:        length of data file
  82.         saturate:        if TRUE, perform saturation */
  83. {
  84. register long     i;            
  85. register double    *source = in;
  86. register short    *destination = out;
  87. register double    value;
  88. register double    ceiling = 32767.0;
  89. register double    floor = -32768.0;
  90.  
  91. /* convert buffer without saturation */
  92. if (saturate == FALSE)
  93.     {
  94.     for (i = length; --i >= 0;) 
  95.     *destination++ = (short) *source++;    
  96.     }
  97. /* convert buffer w/saturation to short range [-32768..32767] */
  98. else
  99.     {
  100.     for (i = length; --i >= 0; destination++) 
  101.     {
  102.     value = *source++;
  103.     if    (value > ceiling)
  104.         *destination = 32767;
  105.     else if (value < floor)
  106.         *destination = -32768;
  107.     else 
  108.         *destination = (short) value;
  109.     }
  110.     }
  111. }    /* ------------------ end DoublesToShorts() --------------- */
  112. /**************************************************************** 
  113.  * ClearDoubles:   fill buffer w/zero-valued DOUBLEs
  114.  *****************************************************************/
  115.     void 
  116. ClearDoubles(double *in, long length)
  117.     /* in:        base address of input data file
  118.        length:  length of data file */
  119. {
  120. register long     i;            
  121. register double    zeroValue = 0.0;    /* zero valued register */
  122. register double    *ptr = in;            /* just some ptr */
  123.  
  124. /* clear buffer */
  125. for (i = length; --i >= 0;) 
  126.     *ptr++ = zeroValue;
  127. }    /* ------------------ end ClearDoubles() --------------- */
  128.  
  129. /*
  130.  * GenerateSawtoothCycle:    generate single cycle, non-bandlimited 
  131.  *                sawtooth wave. 
  132.  * -------------------------------------------------------------------- */
  133.     void
  134. GenerateSawtoothCycle(double *sampleBase, int waveLength)
  135. {
  136. int    i;
  137. double    arg, argInc;
  138.  
  139. /* 
  140.  * compute sawtooth wave.  This process generates a wave of all harmonics
  141.  *    w/amplitude proportional to 1/harmonic #.          
  142.  */
  143. arg = 32767.0;
  144. argInc = 2.0*arg/((double) waveLength);
  145. for (i = 0; i < waveLength; i++, arg -= argInc)
  146.     {
  147.     sampleBase[i] = arg;
  148.     }
  149. }    /* ----------------------- end GenerateSawtoothCycle() --------------------- */
  150.  
  151. /*
  152.  * GenerateTriangleCycle:    generate single cycle, non-bandlimited 
  153.  *                triangle wave. 
  154.  * -------------------------------------------------------------------- */
  155.     void
  156. GenerateTriangleCycle(double *waveMemory, int waveLength)
  157. {
  158. int    i;
  159. double    arg, argInc;
  160.  
  161. /* 
  162.  * compute triangle wave.  This process generates a wave w/odd harmonics only
  163.  *    w/amplitude proportional to 1/(harmonic # squared).          
  164.  */
  165. arg = -32767.0;
  166. argInc = 4.0*32767.0/((double) waveLength);
  167. /* do positive slope portion */
  168. for (i = 0; (i < waveLength)&&(arg <= 32767.0); i++, arg += argInc)
  169.     waveMemory[i] = (double) arg;
  170.  
  171. /* do negative slope portion */
  172. arg = 2.0*32767.0 - arg;    /* mirror xtra back into range */
  173. for (; i < waveLength; i++, arg -= argInc)
  174.     waveMemory[i] = (double) arg;
  175. }    /* ----------------------- end GenerateTriangleCycle() --------------------- */
  176.  
  177. /*
  178.  * GeneratePulseCycle:    generate non-bandlimited pulse wave of specified duty cycle. 
  179.  * -------------------------------------------------------------------- */
  180.     void
  181. GeneratePulseCycle(double *waveMemory, int waveLength, double dutyCycle)
  182. {
  183. int    i;
  184. int    dutyCycleEnd;
  185.  
  186. /* check for valid duty cycle Range:  1..waveLength-1 */
  187. dutyCycleEnd = dutyCycle*((double) waveLength);
  188. if ((dutyCycleEnd <= 0)||(dutyCycle >= waveLength))
  189.     {
  190.     fprintf(stderr, "GeneratePulseCycle(): bogus duty cycle: %f.  No wave, dude\n", 
  191.         dutyCycle);
  192.     return;
  193.     }
  194. /* Here, duty cycle is percentage of wavelength signal positive. 
  195.  * Duty cycle specifies the harmonic relationships.  A pulse function in the
  196.  * time domain transforms into a sin(x)/x or sinc(x) function in the
  197.  * frequency domain.  The value of the sinc function will determine the
  198.  * amplitude of the harmonics.  
  199.  *
  200.  * A square wave (duty cycle 50%) is member of the pulse wave family.  Just 
  201.  * so happens that the frequency domain sinc function for the square wave 
  202.  * is zero at every even harmonic.  Thus, a square wave contains odd only
  203.  * harmonics whose amplitudes are 1/harmonic #.  
  204.  *
  205.  * A pulse wave of 33% duty cycle is missing every third harmonic.
  206.  * A pulse wave of 25% duty cycle is missing every fourth harmonic.
  207.  * And so on, and so on.   However, the present harmonics don't have a 
  208.  * simple 1/harmonic # amplitude relationship.  Need to examin the sinc function.
  209.  * Very small and very large duty cycles have a nasal quality.
  210.  *
  211.  * A traditional method for producing ballsy sounds from a single oscillator
  212.  * is to modulate the duty cycle.  This can be done by computing 400 or so
  213.  * pulse waves w/increasing duty cycles and cycling through this list of
  214.  * waves in a forward backward manner.  THIS IS TERMED PULSE WIDTH MODULATION.
  215.  * The more samples are in your wave, the thinner your thinnest pulse can be.
  216.  * 
  217.  * The modulation rate is determined by the rate at which the pulse widths change.
  218.  * This is determined by the rate at which the pulse wave set is stepped 
  219.  * thru and the number of different pulse waves in the set.
  220.  */
  221. /* do duty cycle portion */
  222. for (i = 0; i < dutyCycleEnd; i++)
  223.     waveMemory[i] = 32767.0;    
  224.  
  225. /*  do off portion */
  226. for (; i < waveLength; i++)
  227.     waveMemory[i] = -32767.0;
  228. }    /* ----------------------- end GeneratePulseCycle() --------------------- */
  229.  
  230. /*
  231.  * GenerateCycle:    generate general wave as sum of of sines of specified 
  232.  *            waveLength.  
  233.  * -------------------------------------------------------------------- */
  234.     void
  235. GenerateCycle(double *waveMemory, int waveLength, double amplitudes[],
  236.         double phases[], double sineTable[])
  237. {
  238. int        i, j;
  239. int        someNumber;
  240. int        sineIndex, sineIncrement;
  241. double        maxValue, someDouble;
  242. double        *wave;
  243.  
  244. /* allocate and clear temporary wave memory */
  245.     wave = (double *) malloc(waveLength*sizeof(double));
  246.     if (wave == NULL)
  247.     {
  248.     fprintf(stderr,"GenerateCycle(): failed to allocate intermediate memory. No wave, dude.\n");
  249.     return;
  250.     }
  251.     ClearDoubles(wave, waveLength);
  252.  
  253. /* generate wave w/specified harmonics at specified amplitudes and phases */
  254.     i = 1;
  255.     while (amplitudes[i] != -1.0)
  256.     {
  257.     if (amplitudes[i] != 0.0)
  258.         {
  259.         /* phase specified in radians.  Convert to nearest sample */
  260.         /* convert to phase in terms of fraction of a cycle */
  261.         someDouble = phases[i];
  262.         someDouble /= twoPi;
  263.         /* extract fractional part */
  264.         someDouble -= (double)((int) someDouble);
  265.         /* convert phase to table index */
  266.         someDouble *= (double) (waveLength-1);
  267.         sineIndex = (int) someDouble;
  268.         for (j = 0; j < waveLength; j++)
  269.         {
  270.         wave[j] += amplitudes[i]*sineTable[sineIndex];
  271.         sineIndex += i;
  272.         /* bound sine table index to actual table */
  273.         if (sineIndex >= waveLength)
  274.             sineIndex -= waveLength;
  275.         }
  276.         }
  277.     i++;
  278.     }
  279.  
  280. /* find largest absolute value in wave */
  281.     maxValue = 0.0;
  282.     for (i = 0; i < waveLength; i++)
  283.         {
  284.         someDouble = wave[i];
  285.         if (someDouble < 0.0)
  286.         someDouble = -someDouble;
  287.         if (someDouble > maxValue)
  288.         maxValue = someDouble;
  289.         }
  290.  
  291. /* write into sample memory.  Product is fit in range -32768..32767 */
  292.     maxValue = 32767.0/maxValue;    /* normalization factor */
  293.     for (i = 0; i < waveLength; i++)
  294.         waveMemory[i] = (double) (maxValue*wave[i]);
  295.  
  296. if (wave != NULL)
  297.     free(wave);
  298. }    /* ----------------------- end GenerateCycle() --------------------- */
  299.  
  300. /*
  301.  * main() 
  302.  * -------------------------------------------------------------------- */
  303. main(int argc, char **argv)
  304. {
  305. int        i, j;
  306. long        n2write, nwrote;
  307. double        arg, argInc;
  308. int        maxHarmonics;
  309.  
  310. /* compute some pi */
  311. pi = 4.0*atan(1.0);
  312. twoPi = 2.0*pi;
  313.  
  314. /* allocate buffers */
  315. cycle = (double *) malloc(waveLength*sizeof(double));
  316. output = (short *) malloc(waveLength*sizeof(short));
  317. if ((cycle == NULL)||(output == NULL))
  318.     {
  319.     fprintf(stderr, "main():  couldn't allocate signal buffers. Exiting ...\n");
  320.     exit(-1);
  321.     }
  322.  
  323. /* allocate memory for sine table, intermediate storage and final product */
  324.     sineTable = (double *) malloc(waveLength*sizeof(double));
  325.     if (sineTable == NULL)
  326.     {
  327.     fprintf(stderr,"main(): failed to allocate sineTable. No wave, dude.\n");
  328.     exit(-1);
  329.     }
  330.       /* generate single cycle of sine */
  331.     argInc = (8.0*atan(1.0))/((double) waveLength);   /* 2*PI/wavelength */
  332.     arg = 0.0;
  333.     for (i = 0; i < waveLength; i++, arg += argInc)
  334.        sineTable[i] = sin(arg);
  335.  
  336. /*
  337.  * initialize setup structure for new file
  338.  */
  339. strcpy(sourceFileName, "tableNet.aifc");
  340. newSetUp = AFnewfilesetup();
  341. /* init # of channels and sampling rate */
  342. AFinitchannels(newSetUp, AF_DEFAULT_TRACK, 1);
  343. AFinitrate(newSetUp, AF_DEFAULT_TRACK, samplingRate);
  344.  
  345. /* open new file */
  346. sourceFile = AFopenfile(sourceFileName, "w", newSetUp);
  347. if (sourceFile == AF_NULL_FILEHANDLE)
  348.     {
  349.     fprintf(stderr, "couldn't open %s\n", sourceFileName);
  350.     exit(1);
  351.     }
  352.  
  353. /*
  354.  * generate waveform table 
  355.  */
  356. fprintf(stderr, "wave table generation initiated for '%s'.\n", sourceFileName);
  357. /* wave 0: sawtooth */     
  358.     GenerateSawtoothCycle(cycle, waveLength); 
  359.     /* write converted data to file */
  360.     DoublesToShorts(cycle, output, waveLength, TRUE);
  361.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  362.  
  363. /* wave 1: triangle wave */
  364.     GenerateTriangleCycle(cycle, waveLength);   
  365.     /* write converted data to file */
  366.     DoublesToShorts(cycle, output, waveLength, TRUE);
  367.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  368.  
  369. /* wave 2: pulse wave of 25% duty cycle*/
  370.     GeneratePulseCycle(cycle, waveLength, 0.25);
  371.     /* write converted data to file */
  372.     DoublesToShorts(cycle, output, waveLength, TRUE);
  373.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  374.  
  375. /* wave 3: square wave */
  376.     GeneratePulseCycle(cycle, waveLength, 0.50);
  377.     /* write converted data to file */
  378.     DoublesToShorts(cycle, output, waveLength, TRUE);
  379.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  380.  
  381. /* wave 4: pulse wave of 75% duty cycle */
  382.     GeneratePulseCycle(cycle, waveLength, 0.75);
  383.     /* write converted data to file */
  384.     DoublesToShorts(cycle, output, waveLength, TRUE);
  385.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  386.  
  387. /* wave 5: sine wave*/
  388.     ClearDoubles(amplitudes, MAX_HARMONICS);
  389.     ClearDoubles(phases, MAX_HARMONICS);
  390.     amplitudes[1] = 1.0;
  391.     phases[1] = 0.0;
  392.     amplitudes[2] = -1.0;
  393.     GenerateCycle(cycle, waveLength, amplitudes, phases, sineTable);
  394.     /* write converted data to file */
  395.     DoublesToShorts(cycle, output, waveLength, TRUE);
  396.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  397.  
  398. /* wave 6: cosine wave */
  399.     ClearDoubles(amplitudes, MAX_HARMONICS);
  400.     ClearDoubles(phases, MAX_HARMONICS);
  401.     amplitudes[1] = 1.0;
  402.     phases[1] = pi/2.0;
  403.     amplitudes[2] = -1.0;
  404.     GenerateCycle(cycle, waveLength, amplitudes, phases, sineTable);
  405.     /* write converted data to file */
  406.     DoublesToShorts(cycle, output, waveLength, TRUE);
  407.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  408.  
  409. /* wave 7 */
  410.     ClearDoubles(amplitudes, MAX_HARMONICS);
  411.     ClearDoubles(phases, MAX_HARMONICS);
  412.     amplitudes[1] = 1.0;
  413.     amplitudes[5] = 1.0/5.0;
  414.     amplitudes[9] = 1.0/9.0;
  415.     amplitudes[10] = -1.0;
  416.     GenerateCycle(cycle, waveLength, amplitudes, phases, sineTable);
  417.     /* write converted data to file */
  418.     DoublesToShorts(cycle, output, waveLength, TRUE);
  419.     nwrote = AFwriteframes(sourceFile, AF_DEFAULT_TRACK, output, waveLength);
  420.  
  421. /* close source file */
  422. AFclosefile(sourceFile);
  423.  
  424. /* deallocate buffers */
  425. if (cycle != NULL)
  426.     free(cycle);
  427. if (output != NULL)
  428.     free(output);
  429. }
  430.  
  431.